using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Xml.Serialization;
using Graffiti.Core;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text.RegularExpressions;

namespace Graffiti.Redirect
{
    [Serializable]
    public class RedirectPlugin : GraffitiEvent
    {
        public override void Init(GraffitiApplication ga)
        {
           ga.BeginRequest += new EventHandler(ga_BeginRequest);
           
        }

        private void ga_BeginRequest(object sender, EventArgs e)
        {
            
            HttpApplication app = sender as HttpApplication;
            Uri uri = HttpContext.Current.Request.Url;

            if (HttpContext.Current.Request.RequestType == "GET")
            {
                if (uri.AbsoluteUri.IndexOf("graffiti-admin") == -1)
                {
                    foreach (RedirectRecord rr in _redirectRecords)
                    {
                        Regex r = new Regex(rr.Regex);
                        Match m = r.Match(uri.AbsoluteUri);

                        if (m.Success)
                        {
                            if (rr.RedirectType == "Permanent (301)")
                            {
                                HttpContext.Current.Response.Status = "301 Moved Permanently";
                                HttpContext.Current.Response.AddHeader("Location", rr.GetTarget(m));
                                HttpContext.Current.Response.End();
                            }
                            else
                            {
                                HttpContext.Current.Response.Redirect(rr.GetTarget(m));
                            }
                        }
                    }
                }
            }
        }


        public List<RedirectRecord> _redirectRecords;

        protected override FormElementCollection AddFormElements()
        {
            FormElementCollection fec = new FormElementCollection();

            fec.Add(new DynamicListElement("List", "Redirect Methods", "Redirect"));
            
            
            return fec;
        }

        protected override NameValueCollection DataAsNameValueCollection()
        {
            NameValueCollection nvc = base.DataAsNameValueCollection();

            if (_redirectRecords != null && _redirectRecords.Count > 0)
            {
                nvc["regex"] = GetRegexString(_redirectRecords);
                nvc["target"] = GetTargetString(_redirectRecords);
                nvc["sptarget"] = GetSpTargetString(_redirectRecords);
                nvc["redirectType"] = GetRedirectTypeString(_redirectRecords);
            }

            return nvc;
        }

        private string GetRegexString(List<RedirectRecord> redirectRecords)
        {
            StringBuilder sb = new StringBuilder();

            foreach(RedirectRecord rr in redirectRecords)
            {
                sb.Append(rr.Regex);
                sb.Append(",");
            }

            if (sb.Length > 0)
            {
                sb.Remove(sb.Length - 1, 1);
            }

            return sb.ToString();
        }
        private string GetTargetString(List<RedirectRecord> redirectRecords)
        {
            StringBuilder sb = new StringBuilder();

            foreach (RedirectRecord rr in redirectRecords)
            {
                sb.Append(rr.Target);
                sb.Append(",");
            }

            if (sb.Length > 0)
            {
                sb.Remove(sb.Length - 1, 1);
            }

            return sb.ToString();
        }
        private string GetSpTargetString(List<RedirectRecord> redirectRecords)
        {
            StringBuilder sb = new StringBuilder();

            foreach (RedirectRecord rr in redirectRecords)
            {
                sb.Append(rr.SpecialTarget);
                sb.Append(",");
            }

            if (sb.Length > 0)
            {
                sb.Remove(sb.Length - 1, 1);
            }

            return sb.ToString();
        }
        private string GetRedirectTypeString(List<RedirectRecord> redirectRecords)
        {
            StringBuilder sb = new StringBuilder();

            foreach (RedirectRecord rr in redirectRecords)
            {
                sb.Append(rr.RedirectType);
                sb.Append(",");
            }

            if (sb.Length > 0)
            {
                sb.Remove(sb.Length - 1, 1);
            }

            return sb.ToString();
        }

        public override StatusType SetValues(HttpContext context, NameValueCollection nvc)
        {
            StatusType statusType = base.SetValues(context, nvc);
            _redirectRecords = new List<RedirectRecord>();

            if (statusType == StatusType.Success)
            {
                _redirectRecords = RedirectRecord.DeSerialize(nvc);
            }

            return statusType;
        }

        public override bool IsEditable
        {
            get
            {
                return true;
            }
        }

        public override string Description
        {
            get
            {
                return "Redirect Plugin";
            }
        }


        public override string Name
        {
            get
            {
                return "Redirect";
            }
        }
    }
}         
